package com.zhj.multiple.core;

import com.zhj.multiple.constant.MultipleConstant;
import com.zhj.multiple.properties.MultipleStategyProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import javax.annotation.Resource;

/**
 * 　　　　　　　   ┏┓　   ┏┓+ +
 * 　　　　　　　┏┛┻━━━┛┻┓ + +
 * 　　　　　　　┃　　　　　　　┃
 * 　　　　　　　┃　　　━　　　┃ ++ + + +
 * 　　　　　　 ████━████ ┃+
 * 　　　　　　　┃　　　　　　　┃ +
 * 　　　　　　　┃　　　┻　　　┃
 * 　　　　　　　┃　　　　　　　┃ + +
 * 　　　　　　　┗━┓　　　┏━┛
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃ + + + +
 * 　　　　　　　　　┃　　　┃			God beast body, code no BUG
 * 　　　　　　　　　┃　　　┃ +			神兽护体,代码无BUG
 * 　　　　　　　　　┃　　　┃
 * 　　　　　　　　　┃　　　┃　　+
 * 　　　　　　　　　┃　 　　┗━━━┓ + +
 * 　　　　　　　　　┃ 　　　　　　　┣┓
 * 　　　　　　　　　┃ 　　　　　　　┏┛
 * 　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +
 * 　　　　　　　　　　┃┫┫　┃┫┫
 * 　　　　　　　　　　┗┻┛　┗┻┛+ + + +
 *
 * @title: 公共的抽象路由类
 * @author zhonghaijun
 * @date 2021-02-23
 */
@EnableConfigurationProperties({MultipleStategyProperties.class})
@Data
@Slf4j
public abstract class AbstractRouting implements IRoutingInterface, InitializingBean {

    /**
     * 数据源配置类
     */
    @Resource
    private MultipleStategyProperties multipleStategyProperties;

    /**
     * 计算字段的hash值
     * @param routingFiled
     * @return
     */
    @Override
    public Integer getRoutingFileHashCode(String routingFiled){
        return Math.abs(routingFiled.hashCode());
    }

    /**
     * 获取表的后缀
     * @param tableIndex 表索引
     */
    @Override
    public String getFormatTableSuffix(Integer tableIndex){
        //获取连接符
        String tableSuffixConnect = multipleStategyProperties.getTableSuffixConnect();
        //根据配置风格格式化表后缀名称
        String format = String.format(multipleStategyProperties.getTableSuffixStyle(), tableIndex);
        return tableSuffixConnect + format;
    }


    /**
     * 工程启动时，检验配置的数据源是否跟策略相似，实现了 InitializingBean 初始化后会执行当前方法
     */
    @Override
    public void afterPropertiesSet(){
        switch (multipleStategyProperties.getRoutingStategy()) {
            case MultipleConstant.ROUTING_DS_TABLE_STATEGY:
                checkRoutingDsTableStategyConfig();
                break;
            case MultipleConstant.ROUTGING_DS_STATEGY:
                checkRoutingDsStategyConfig();
                break;
            default:
                checkRoutingTableStategyConfig();
                break;
        }
    }

    /**
     * 检查多库 多表配置
     */
    private void checkRoutingDsTableStategyConfig() {
        if(multipleStategyProperties.getTableNum()<=1 ||multipleStategyProperties.getDataSourceNum()<=1){
            log.error("你的配置项routingStategy:{}是多库多表配置,数据库个数>1," +
                            "每一个库中表的个数必须>1,您的配置:数据库个数:{},表的个数:{}",multipleStategyProperties.getRoutingStategy(),
                    multipleStategyProperties.getDataSourceNum(),multipleStategyProperties.getTableNum());
            throw new RuntimeException();
        }
    }

    /**
     * 检查多库一表的路由配置项
     */
    private void checkRoutingDsStategyConfig() {
        if(multipleStategyProperties.getTableNum()!=1 ||multipleStategyProperties.getDataSourceNum()<=1){
            log.error("你的配置项routingStategy:{}是多库一表配置,数据库个数>1," +
                            "每一个库中表的个数必须=1,您的配置:数据库个数:{},表的个数:{}",multipleStategyProperties.getRoutingStategy(),
                    multipleStategyProperties.getDataSourceNum(),multipleStategyProperties.getTableNum());
            throw new RuntimeException();
        }
    }

    /**
     * 检查一库多表的路由配置项
     */
    private void checkRoutingTableStategyConfig() {
        if(multipleStategyProperties.getTableNum()<=1 ||multipleStategyProperties.getDataSourceNum()!=1){
            log.error("你的配置项routingStategy:{}是一库多表配置,数据库个数=1," +
                            "每一个库中表的个数必须>1,您的配置:数据库个数:{},表的个数:{}",multipleStategyProperties.getRoutingStategy(),
                    multipleStategyProperties.getDataSourceNum(),multipleStategyProperties.getTableNum());
            throw new RuntimeException();
        }
    }



}
